package main
import "fmt"

/*
type File struct {
	//
}

//定义了一个File类，实现有REad,Write,Seek,Close等方法
func (f *File) Read(buf []byte) (n int, err error) {}
func (f *File) Write(buf []byte) (n int,err error) {}
func (f *File) Seek(off int64,whence int) (pos int64, err error) {}
func (f *File) Close() error {}

//假如我们有以下接口
type IFile interface {
	Read(buf []byte) (n int, err error)
	Write(buf []byte) (n int,err error)
	Seek(off int64,whence int) (pos int64, err error)
	Close() error
}

type IReader interface {
	Read(buf []byte) (n int, err error)
}

type IWriter interface {
	Write(buf []byte) (n int,err error)
}

type ICloser interface {
	Close() error
}

func test1() {
	//尽管File类并没有从这些接口继承，甚至不知道这些接口的存在，但是实现了接口里的方法
	//，所以可以进行赋值
	var f1 IFile = new(File)
	var f2 IReader = new(File)
	var f3 IWriter = new(File)
	var f4 ICloser = new(File)
}
*/

////////////////////////////
type Integer int
func (a Integer) Less(b Integer) bool {
	return a < b
}
/*编译器会为上面的方法生成一个指针类型方法
func (a *Integer) Less(b Integer) bool {
	return a < b
}*/

//但不会为下面的指针方法生成非指针的方法，因为指针方法要求引用语义
func (a *Integer) Add(b Integer) {
	*a += b
}

type LessAdder interface {
	Less(b Integer) bool
	Add(b Integer)
}

func test2() {
	var a Integer = 1
	var b LessAdder = &a
	//var b2 LessAdder = a //不能这样赋值，非指针类型并未实现所有方法
	fmt.Println(b)
}

func test3() {
	//interface{} 相当于Any类型
	var v1 interface{} = 1
	var v2 interface{} = "abc"
	var v3 interface{} = &v2
	var v4 interface{} = struct { X int } {1}
	var v5 interface{} = &v4
	fmt.Println(v1,v2,v3,v4,v5)
}

/////////// the go programming language ch7
type ByteCounter int
func (c *ByteCounter) Write(p []byte) (int, error) {
	*c += ByteCounter(len(p))//convert int to ByteCounter
	return len(p),nil
}
func test4() {
	var c ByteCounter
	c.Write([]byte("hello"))
	fmt.Println(c) //因为ByteCounter实现了Write方法，所以可以直接打印

}

type my struct {
	a int
}
func doStuff(in interface{}) {
	in.a = 1
}
//https://stackoverflow.com/questions/27178635/cast-a-struct-pointer-to-interface-pointer-in-golang
func t_no_such_interface_pointer() {


}

func main() {
	test4()
	//test2()	
}